#include "../mqserver/route.hpp"
#include <gtest/gtest.h>

using namespace std;
using namespace ns_rabbitmq;

class RouteTets : public testing::Environment
{
public:
    virtual void SetUp() override
    {
    }
    virtual void TearDown() override
    {
        // emp->clear();
        cout << "完成清理工作" << endl;
    }
};

TEST(route_test, legal_routing_key)
{
    std::string rkey1 = "news.music.pop";
    std::string rkey2 = "news..music.pop";
    std::string rkey3 = "news..music.pop....";
    std::string rkey4 = ".news,.music.pop";
    std::string rkey5 = ".news_..music1234.ZApop";

    ASSERT_EQ(ns_rabbitmq::Router::IsRoutingKeylegal(rkey1), true);
    ASSERT_EQ(Router::IsRoutingKeylegal(rkey2), true);
    ASSERT_EQ(Router::IsRoutingKeylegal(rkey3), true);
    ASSERT_EQ(Router::IsRoutingKeylegal(rkey4), false);
    ASSERT_EQ(Router::IsRoutingKeylegal(rkey5), true);
}

TEST(binding_test, legal_binding_key)
{
    std::string bkey1 = "news.music.pop.#";
    std::string bkey2 = "news..music.pop.#.*.top";
    std::string bkey3 = "news..music.pop....#";
    std::string bkey4 = ".news,.music.pop.####";
    std::string bkey5 = ".news_..music1234.ZApop";

    ASSERT_EQ(ns_rabbitmq::Router::IsBindingKeylegal(bkey1), true);
    ASSERT_EQ(Router::IsBindingKeylegal(bkey2), false);
    ASSERT_EQ(Router::IsBindingKeylegal(bkey3), true);
    ASSERT_EQ(Router::IsBindingKeylegal(bkey4), false);
    ASSERT_EQ(Router::IsBindingKeylegal(bkey5), true);
}

TEST(route_test, route)
{
    std::vector<std::string> binding{
        "aaa",
        "aaa.bbb",
        "aaa.bbb",
        "aaa.bbb",
        "aaa.#.bbb",
        "aaa.bbb.#",
        "#.bbb.ccc",
        "aaa.bbb.ccc",
        "aaa.*",
        "aaa.*.bbb",
        "*.aaa.bbb",
        "#",
        "aaa.#",
        "aaa.#",
        "aaa.#.ccc",
        "aaa.#.ccc",
        "aaa.#.ccc",
        "#.ccc",
        "#.ccc",
        "aaa.#.ccc.ccc",
        "aaa.#.bbb.*.bbb"};
    std::vector<std::string> routing{"aaa",
                                     "aaa.bbb",
                                     "aaa.bbb.ccc",
                                     "aaa.ccc",
                                     "aaa.bbb.ccc",
                                     "aaa.ccc.bbb",
                                     "aaa.bbb.ccc.ddd",
                                     "aaa.bbb.ccc",
                                     "aaa.bbb",
                                     "aaa.bbb.ccc",
                                     "aaa.bbb",
                                     "aaa.bbb.ccc",
                                     "aaa.bbb",
                                     "aaa.bbb.ccc",
                                     "aaa.ccc",
                                     "aaa.bbb.ccc",
                                     "aaa.aaa.bbb.ccc",
                                     "ccc",
                                     "aaa.bbb.ccc",
                                     "aaa.bbb.ccc.ccc.ccc",
                                     "aaa.ddd.ccc.bbb.eee.bbb"

    };

    std::vector<bool> result = {
        true,
        true,
        false,
        false,
        false,
        false,
        false,
        true,
        true,
        false,
        false,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true,
        true};

    for (int i = 0; i < routing.size(); i++)
    {
        ASSERT_EQ(Router::Route(ExchangeType::TOPIC, routing[i], binding[i]), result[i]);
    }
}
int main(int argc, char *argv[])
{
    testing::InitGoogleTest(&argc, argv);
    testing::AddGlobalTestEnvironment(new RouteTets);
    RUN_ALL_TESTS();
    return 0;
}

// aaa aaa true
// aaa.bbb aaa.bbb true
// aaa.bbb aaa.bbb.ccc false
// aaa.bbb aaa.ccc false
// aaa.#.bbb aaa.bbb.ccc false
// aaa.bbb.# aaa.ccc.bbb false
// #.bbb.ccc aaa.bbb.ccc.ddd false
// aaa.bbb.ccc aaa.bbb.ccc true
// aaa.* aaa.bbb true
// aaa.*.bbb aaa.bbb.ccc false
// *.aaa.bbb aaa.bbb false
// # aaa.bbb.ccc true
// aaa.# aaa.bbb true
// aaa.# aaa.bbb.ccc true
// aaa.#.ccc aaa.ccc true
// aaa.#.ccc aaa.bbb.ccc true
// aaa.#.ccc aaa.aaa.bbb.ccc true
// #.ccc ccc true
// #.ccc aaa.bbb.ccc true
// aaa.#.ccc.ccc aaa.bbb.ccc.ccc.ccc true
// aaa.#.bbb.*.bbb aaa.ddd.ccc.bbb.eee.bbb true